using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Drawing.Text;

namespace Camalon.Drawing
{
	public enum TextDirection
	{
		Horizontal,
		VerticalTopToBottom,
		VerticalBottomToTop
	}

	[TypeConverter(typeof(ReadOnlyObjectConverter))]
	public class TextFormat:ICloneable, IDisposable	
	{
		[Browsable(false)]
		protected internal event EventHandler InternalChanged	= null;

		private StringFormatFlags	_formatFlags;
		private StringTrimming		_trimming;
		private ContentAlignment	_alignment;
		private StringAlignment		_textAlignment;
		private StringAlignment		_lineAlignment;
		private bool				_typographic;
		private TextDirection		_vertical;

		private				bool	_transform;
//		private				bool	_embedded;



		public TextFormat()
		{
			this.Reset();
		}

		public void Reset()
		{
			_formatFlags		=	
				StringFormatFlags.LineLimit|
				StringFormatFlags.NoWrap|
				StringFormatFlags.MeasureTrailingSpaces;

			_trimming			=	StringTrimming.Character;
			_alignment			=	ContentAlignment.MiddleCenter;
			_textAlignment		=	StringAlignment.Center;
			_lineAlignment		=	StringAlignment.Center;
			_typographic		=	false;
			_vertical			=	TextDirection.Horizontal;
			_transform			=	true;
//			_embedded			=	true;

			InvokeInternalChanged();

		}


		#region IDisposable Members

		public void Dispose()
		{
			Delegate.RemoveAll( InternalChanged, InternalChanged);
			this.InternalChanged = null;
		}
		
		#endregion

		#region ICloneable Members

		public object Clone()
		{
			TextFormat format = this.MemberwiseClone() as TextFormat;
			Delegate.RemoveAll( format.InternalChanged,format.InternalChanged );
			format.InternalChanged = null;
			return format;
		}

		#endregion

		protected internal bool IsDefault()
		{

			return _formatFlags		==	
				(StringFormatFlags.LineLimit|
				StringFormatFlags.NoWrap|
				StringFormatFlags.MeasureTrailingSpaces) &&
			_trimming			==	StringTrimming.Character&&
			_alignment			==	ContentAlignment.MiddleCenter&&
			_textAlignment		==	StringAlignment.Center&&
			_lineAlignment		==	StringAlignment.Center&&
			_typographic		==	false&&
			_vertical			==	TextDirection.Horizontal&&
			_transform			==	true;//&&
//			_embedded			==	true;


		}

		public bool IsEqual( TextFormat textFormat )
		{
			if( textFormat == null) return false;
			return 
				textFormat.FormatFlags			== _formatFlags		&&
				textFormat.Trimming				== _trimming		&&
				textFormat.Alignment			== _alignment		&&
				textFormat.TextAlignment		== _textAlignment	&&
				textFormat.LineAlignment		== _lineAlignment	&&
				textFormat.Typographic			== _typographic		&&
				textFormat.TextDirection		== _vertical		&&
				textFormat.Transform			== _transform;//		&&
//				textFormat.Embedded				== _embedded		;
		}

		protected void InvokeInternalChanged()
		{
			if( InternalChanged != null) InternalChanged( this, new EventArgs());
		}


//		[DefaultValue( true )]
//		public bool Embedded
//		{
//			get{ return _embedded;}
//			set
//			{
//				_embedded = value;
//				InvokeInternalChanged();
//
//			}
//		}

		[DefaultValue( true )]
		public bool Transform
		{
			get{ return _transform;}
			set
			{
				_transform = value;
				InvokeInternalChanged();

			}
		}


		#region StringFormatFlags


		[Browsable(false), DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden)]
		public StringFormatFlags FormatFlags
		{
			get{ return _formatFlags;}
		}


		[DefaultValue(false)]
		[RefreshProperties( RefreshProperties.Repaint)]
		public bool RightToLeft
		{
			get
			{
				StringFormatFlags enumVal = (StringFormatFlags)Enum.Parse(typeof(StringFormatFlags), "DirectionRightToLeft");
				return (_formatFlags & enumVal) > 0;
			}
			set
			{
				StringFormatFlags flag = (StringFormatFlags)Enum.Parse(typeof(StringFormatFlags), "DirectionRightToLeft");
				if( value)
					_formatFlags |=  flag;
				else
					_formatFlags ^= flag;

				InvokeInternalChanged();
			}
		}

		[DefaultValue(TextDirection.Horizontal)]
		[RefreshProperties( RefreshProperties.Repaint)]
		public TextDirection TextDirection
		{
			get
			{
				return _vertical;
//				StringFormatFlags enumVal = (StringFormatFlags)Enum.Parse(typeof(StringFormatFlags), "DirectionVertical");
//				return ((_formatFlags & enumVal) > 0);
			}
			set
			{
				if( _vertical == value) return;

				StringFormatFlags flag = (StringFormatFlags)Enum.Parse(typeof(StringFormatFlags), "DirectionVertical");
				if( value == TextDirection.Horizontal )
					_formatFlags ^= flag;//Clear
				else 
					_formatFlags |=  flag;//Set
				
				_vertical = value;

				InvokeInternalChanged();
			}
		}


		[DefaultValue(true)]
		[RefreshProperties( RefreshProperties.Repaint)]
		public bool NoWrap
		{
			get
			{
				StringFormatFlags enumVal = (StringFormatFlags)Enum.Parse(typeof(StringFormatFlags), "NoWrap");
				return (_formatFlags & enumVal) > 0;
			}
			set
			{
				StringFormatFlags flag = (StringFormatFlags)Enum.Parse(typeof(StringFormatFlags), "NoWrap");
				if( value)
					_formatFlags |=  flag;
				else
					_formatFlags ^= flag;

				InvokeInternalChanged();
			}
		}

		#region COMMEMTED FLAGS
//-------------------------------------------------------------------------------------------------------------------
//		[DefaultValue(false)]
//		[RefreshProperties( RefreshProperties.Repaint)]
//		public bool NoClip
//		{
//			get
//			{
//				StringFormatFlags enumVal = (StringFormatFlags)Enum.Parse(typeof(StringFormatFlags), "NoClip");
//				return (_formatFlags & enumVal) > 0;
//			}
//			set
//			{
//				StringFormatFlags flag = (StringFormatFlags)Enum.Parse(typeof(StringFormatFlags), "NoClip");
//				if( value)
//					_formatFlags |=  flag;
//				else
//					_formatFlags ^= flag;
//
//				InvokeInternalChanged();
//			}
//		}
//-------------------------------------------------------------------------------------------------------------------
//		[DefaultValue(false)]
//		[RefreshProperties( RefreshProperties.Repaint)]
//		public bool FitBlackBox
//		{
//			get
//			{
//				StringFormatFlags enumVal = (StringFormatFlags)Enum.Parse(typeof(StringFormatFlags), "FitBlackBox");
//				return (_formatFlags & enumVal) > 0;
//			}
//			set
//			{
//				StringFormatFlags flag = (StringFormatFlags)Enum.Parse(typeof(StringFormatFlags), "FitBlackBox");
//				if( value)
//					_formatFlags |=  flag;
//				else
//					_formatFlags ^= flag;
//
//				InvokeInternalChanged();
//			}
//		}
//-------------------------------------------------------------------------------------------------------------------
//		[DefaultValue(false)]
//		[RefreshProperties( RefreshProperties.Repaint)]
//		public bool LineLimit
//		{
//			get
//			{
//				StringFormatFlags enumVal = (StringFormatFlags)Enum.Parse(typeof(StringFormatFlags), "LineLimit");
//				return (_formatFlags & enumVal) > 0;
//			}
//			set
//			{
//				StringFormatFlags flag = (StringFormatFlags)Enum.Parse(typeof(StringFormatFlags), "LineLimit");
//				if( value)
//					_formatFlags |=  flag;
//				else
//					_formatFlags ^= flag;
//
//				InvokeInternalChanged();
//			}
//		}
//-------------------------------------------------------------------------------------------------------------------

		#endregion COMMEMTED FLAGS

		#endregion StringFormatFlags

		#region Alignment
		//Does not work in GraphicsPaths
//		[DefaultValue(TextRenderingHint.AntiAlias)]
//		[RefreshProperties( RefreshProperties.Repaint)]
//		public TextRenderingHint TextRendering
//		{
//			get{ return _textRendering;}
//			set
//			{
//				if( _textRendering == value) return;
//				_textRendering = value;
//
//				InvokeInternalChanged();
//			}
//		}

		[DefaultValue(false)]
		[RefreshProperties( RefreshProperties.Repaint)]
		public bool Typographic
		{
			get{ return _typographic;}
			set
			{
				if( _typographic == value) return;
				_typographic = value;
				InvokeInternalChanged();
			}
		}


		[DefaultValue(StringTrimming.Character)]
		[RefreshProperties( RefreshProperties.Repaint)]
		public StringTrimming Trimming
		{
			get
			{  
				return _trimming;
			}
			set
			{
				if( _trimming == value ) return;
				_trimming = value;

				InvokeInternalChanged();
			}
		}
		
		[DefaultValue(ContentAlignment.MiddleCenter)]
		[RefreshProperties( RefreshProperties.Repaint)]
		public ContentAlignment Alignment
		{
			get{ return _alignment;}
			set
			{
				if( _alignment == value) return;

				_alignment = value;

				switch( value)
				{
					case ContentAlignment.BottomCenter:
						_textAlignment = StringAlignment.Center;
						_lineAlignment = StringAlignment.Far;
						break;
					case ContentAlignment.BottomLeft:
						_textAlignment = StringAlignment.Near;
						_lineAlignment = StringAlignment.Far;
						break;
					case ContentAlignment.BottomRight:
						_textAlignment = StringAlignment.Far;
						_lineAlignment = StringAlignment.Far;
						break;
					case ContentAlignment.MiddleCenter:
						_textAlignment = StringAlignment.Center;
						_lineAlignment = StringAlignment.Center;
						break;
					case ContentAlignment.MiddleLeft:
						_textAlignment = StringAlignment.Near;
						_lineAlignment = StringAlignment.Center;
						break;
					case ContentAlignment.MiddleRight:
						_textAlignment = StringAlignment.Far;
						_lineAlignment = StringAlignment.Center;
						break;
					case ContentAlignment.TopCenter:
						_textAlignment = StringAlignment.Center;
						_lineAlignment = StringAlignment.Near;
						break;
					case ContentAlignment.TopLeft:
						_textAlignment = StringAlignment.Near;
						_lineAlignment = StringAlignment.Near;
						break;
					case ContentAlignment.TopRight:
						_textAlignment = StringAlignment.Far;
						_lineAlignment = StringAlignment.Near;
						break;

				}
				InvokeInternalChanged();
			}
		}


		[Browsable(false)]
		protected internal StringAlignment TextAlignment
		{	get{ return _textAlignment;}	}


		[Browsable(false)]
		protected internal StringAlignment LineAlignment
		{	get{ return _lineAlignment;}	}


		#endregion Alignment

	}


}
